package com.jike.jkgame.data;

import java.util.Arrays;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONObject;

import com.jike.jkgame.db.ResourcesDAO;

public class MissionManager {
	private static MissionManager mInstance;

	private int mCurCityIdx = -1;

	private int mCurEventIdx = -1;

	private List<City> mCities;

	private List<Event> mEvents;

	private List<Mission> mMissions;

	private MissionManager() {
		ResourcesDAO dao = ResourcesDAO.get();

		mCities = dao.getAllCities();
		mCurCityIdx = 0;
	}

	public static MissionManager get() {
		if (mInstance == null) {
			mInstance = new MissionManager();
		}

		return mInstance;
	}
	
	public int getCurrentCityId() {
		if (mCities == null || mCurCityIdx == -1) {
			return -1;
		}

		return mCities.get(mCurCityIdx).id;
	}
	
	public int getCurrentCityIdx() {
		return mCurCityIdx;
	}
	
	public void setCurrentCity(int cityId) {
		mCurCityIdx = indexCityById(cityId);
		loadEvents(cityId);
	}
	
	public City getCurrentCity() {
		if (mCities == null || mCurCityIdx == -1) {
			return null;
		}
		return mCities.get(mCurCityIdx);
	}
	
	private int indexCityById(int cityId) {
		if (mCities == null) {
			return -1;
		}

		int h = mCities.size() - 1;
		int l = 0;
		int m = (h + l) / 2;

		while (l <= h) {
			int id = mCities.get(m).id;
			if (id == cityId) {
				return m;
			} else if (id > cityId) {
				h = m - 1;
			} else {
				l = m + 1;
			}
			m = (h + l) / 2;
		}

		return -1;
	}

	public DoMissionResult finishMission(int id, int count) {
		DoMissionResult result = new DoMissionResult();
		int idx = indexMissionById(id);
		Mission m = mMissions.get(idx);
		if (count >= m.completeness || count == 0) {
			result.finished = true;
			m.enabled = false;
			m.finish_cnt = m.completeness;

			if (idx == mMissions.size() - 1) {
				enableNextEvent();
				result.next = true;
			} 
			
		} else {
			m.finish_cnt = count;
		}
		return result;
	}
	
	private int indexEventById(int eventid) {
		if (mEvents == null) {
			return -1;
		}

		int h = mEvents.size() - 1;
		int l = 0;
		int m = (h + l) / 2;

		while (l <= h) {
			int id = mEvents.get(m).id;
			if (id == eventid) {
				return m;
			} else if (id > eventid) {
				h = m - 1;
			} else {
				l = m + 1;
			}
			m = (h + l) / 2;
		}

		return -1;
	}

	public void setCurrentEvent(int eventId) {
		mCurEventIdx = indexEventById(eventId);
		loadMissions(eventId);
	}

	public void loadEvents(int cityId) {
		ResourcesDAO dao = ResourcesDAO.get();
		mEvents = dao.getAllEvents(cityId);

	}
	
	public int getCurrentEventIndex() {
		return mCurEventIdx;
	}

	public int getCurrentMission2LevelId() {
		if (mEvents == null || mCurEventIdx == -1) {
			return -1;
		}

		return mEvents.get(mCurEventIdx).id;
	}

	public void loadMissions(int parentId) {

		ResourcesDAO dao = ResourcesDAO.get();
		mMissions = dao.getAllMissions(parentId);
	}

	public void enableNextEvent() {
		if (mCurEventIdx == mEvents.size() - 1) {
			if (mCurCityIdx >= mCities.size() - 1) {
				// 完成了所有任务
				mCurCityIdx = 0;
			} else {
				mCurCityIdx++;
			}
			mCities.get(mCurCityIdx).enabled = true;
			loadEvents(getCurrentCityId());
			mCurEventIdx = 0;
			loadMissions(getCurrentMission2LevelId());
		} else {
			mCurEventIdx++;
			loadMissions(getCurrentMission2LevelId());
		}
	}

	public List<City> getCities() {
		return this.mCities;
	}

	public List<Event> getEvents() {
		return this.mEvents;
	}

	public List<Mission> getMissions() {
		return this.mMissions;
	}

	/**
	 * 设置当前可以做的二级任务，此函数必须在{@link #setCurrentMission1Level(int id)}之后调用
	 * 
	 * @param ids
	 */
	public void setEnabledEvents(int[] ids) {
		if (ids == null) {
			return;
		}
		
		Arrays.sort(ids);
		int idx = 0;
		for (int id : ids) {
			while (idx < mEvents.size()) {
				if (mEvents.get(idx).id < id) {
					mEvents.get(idx).enabled = false;
					idx++;
					continue;
				} else if (mEvents.get(idx).id > id) {
					break;
				} else {
					mEvents.get(idx).enabled = true;
					idx++;
					break;
				}

			}
		}

	}

	private int indexMissionById(int id) {

		if (mMissions == null) {
			return -1;
		}

		// 因为一般mMissions的个数比较少，应该在5个左右，所以直接遍历
		for (int i = 0; i < mMissions.size(); ++i) {
			if (mMissions.get(i).id == id) {
				return i;
			}
		}
		return -1;
	}

	private Mission findMissionById(int id) {
		if (mMissions == null) {
			return null;
		}

		for (Mission m : mMissions) {
			if (m.id == id) {
				return m;
			}
		}
		return null;
	}

	public void updateMission(int id, int finish_cnt, int level, boolean enable) {
		Mission m = findMissionById(id);

		if (m != null) {
			m.finish_cnt = finish_cnt;
			m.level = level;
			m.enabled = enable;
		}
	}

	public void updateMissions(JSONArray missions) {
		if (missions == null) {
			return;
		}
		for (int i = 0; i < missions.length(); ++i) {
			JSONObject m = missions.optJSONObject(i);
			if (m == null) {
				continue;
			}
			int id = m.optInt("id");
			int finish_cnt = m.optInt("finish");
			int level = m.optInt("level");
			boolean enable = (m.optInt("enable") != 0);
			updateMission(id, finish_cnt, level, enable);
		}

	}

	public int updateMissions(int secondLevelId, JSONArray missions) {
		int firstEnable = 0;
		if (getCurrentMission2LevelId() != secondLevelId) {
			setCurrentEvent(secondLevelId);
		}
		if (missions == null) {
			return firstEnable;
		}
		for (int i = 0; i < missions.length(); ++i) {
			JSONObject m = missions.optJSONObject(i);
			if (m == null) {
				continue;
			}
			int id = m.optInt("id");
			int finish_cnt = m.optInt("finish");
			int level = m.optInt("level");
			boolean enable = (m.optInt("enable") != 0);
			if (enable && firstEnable == 0) {
				firstEnable = i;
			}
			updateMission(id, finish_cnt, level, enable);
		}
		
		return firstEnable;

	}

	public static class DoMissionResult {
		public boolean finished;
		public boolean next;
	}

}
